package learn;

import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;


//实现一个阻塞队列
class BlockQueue_1 {
    private Object locker = new Object();
    private int size;
    private Object[] blockQ;
    private volatile int top,end;
    private int useSize;
    public BlockQueue_1(int size) {
        this.size = size;
        blockQ = new Object[size];
        top = 0;
        end = 0;
        useSize = 0;
    }

    //加入队列
    public void take(Object task) {
        while(isFull()) {//满了就等待，当他有空位了就唤醒
            synchronized (locker) {
                try {
                    System.out.println("满了等待拿取");
                    locker.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        synchronized (locker) {
            if (end >= size) {//循环
                end = 0;
            }
            blockQ[end] = task;
            end++;
            locker.notify();
            useSize++;
        }
    }

    public Object get() {
        while(isEmpty()) {
            synchronized (locker) {//空了就得等他加入新的
                try {
                    System.out.println("空了等待加u");
                    locker.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        synchronized (locker) {//防止多线程下多个线程获取同一个任务
            if (top >= size) {
                top = 0;
            }
            Object ret = blockQ[top];
            top++;
            useSize--;
            locker.notify();
            return ret;
        }
    }

    private boolean isFull() {
        return (end + 1) % size == top;
    }

    private boolean isEmpty() {
        return top == end;
    }

    public int getSize() {
        return useSize;
    }

    public static void main(String[] args) {
        BlockQueue_1 b = new BlockQueue_1(4);
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("s1");
            }
        };
        Runnable r2 = new Runnable() {
            @Override
            public void run() {
                System.out.println("s2");
            }
        };
        b.take(r1);
        b.take(r2);
        b.take(r2);
        Object get = b.get();
        Runnable rr = (Runnable) get;
        rr.run();
        b.take(r2);
        b.take(r2);
//        System.out.println(b.getSize());
    }
}

//创建线程
//继承 Thread, 重写 run
class method1 extends Thread {
    @Override
    public void run() {
        System.out.println("extends thread 1 run");
    }
}
//实现一个单例模式
class singleHug {
    //饿汉模式
    private static singleHug s = new singleHug();

    public singleHug getInstance() {
        return s;
    }

    private singleHug() {}
}

class single{
    //懒汉模式
    Object locker = new Object();
    private volatile static single s = null;

    public single getInstance() {
        if (s == null) {//表示不为空了，也不用加锁了
            synchronized (locker) {//避免并发导致多创建了对象
                if (s == null) {
                    s = new single();
                }
            }
        }
        return s;
    }

    private single() {}
}



public class work {
    static Object locker = new Object();
    static Object locker1 = new Object();
    static Object locker2 = new Object();
    static Object locker3 = new Object();

    /**
     * Callable是一个接口，能使线程结束后有个返回值
     * 使用功能FutureTask来获取这个返回值
     */
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable<Integer> callable = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return 0;
            }
        };
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        Thread t = new Thread(futureTask);
        t.start();
        int f = futureTask.get();
        System.out.println(f);
    }
    public static void main7(String[] args) throws InterruptedException {
        Thread t1 = new Thread(()->{
            synchronized (locker3) {
                try {
                    locker3.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println("b");
            synchronized (locker1) {
                locker1.notify();
            }
        },"b");
        Thread t2 = new Thread(() -> {
            try {
                t1.join();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(Thread.currentThread().getName());
            synchronized (locker1) {
                try {
                    locker1.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println("a");
            synchronized (locker2) {
                locker2.notify();
            }
        }, "a");

        Thread t3 = new Thread(() -> {
            synchronized (locker2) {
                try {
                    locker2.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println("c");
            synchronized (locker3) {
                locker3.notify();
            }

        }, "c");
        t1.start();
        t2.start();
        t3.start();
        Thread.sleep(1000);
        synchronized (locker2) {
            locker2.notify();
        }
    }
    //死锁
    public static void main6(String[] args) throws InterruptedException {

        Thread t1 = new Thread(() -> {
            synchronized (locker1) {
                System.out.println("获取第一把锁");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                synchronized (locker2) {
                    System.out.println("获取第二吧锁");

                }
            }
        });
        Thread t2 = new Thread(() -> {
            synchronized (locker2) {
                System.out.println("获取第二吧锁");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                synchronized (locker1) {
                    System.out.println("获取第一把锁");
                }
            }
        });
        t1.start();

        t2.start();
    }
    public static void main5(String[] args) throws InterruptedException {
        synchronized (locker3) {
//            locker2.wait();
            locker3.notify();

        }
    }
    public static void main4(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                synchronized (locker3) {
                    try {
                        locker3.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                }
                System.out.print("A");
                synchronized (locker1) {
                    locker1.notify();
                }
            }
            });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                synchronized (locker1) {
                    try {
                        locker1.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                }
                System.out.print("B");
                synchronized (locker2) {

                    locker2.notify();
                }
            }
            });
        Thread t3 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                synchronized (locker2) {
                    try {
                        locker2.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                }
                System.out.println("C");
                synchronized (locker3) {
                    locker3.notify();
                }
            }
        });
        t1.start();
        t2.start();
        t3.start();
        Thread.sleep(1000);
        synchronized (locker3) {
            System.out.println("huanxing");
            locker3.notify();
        }
    }
    static int sum = 0;

    public static void main3(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                synchronized (locker) {
                    sum++;
                }

            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                synchronized(locker){
                    sum++;
                }
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("sum = " + sum);
    }

    static int evenNum = 0;
    static int oddNum = 0;
    public static void main2(String[] args) throws InterruptedException {
        int[] longArr = new int[10_000_000];
        Random r = new Random();
        for (int i = 0; i < longArr.length; i++) {
            longArr[i] = r.nextInt(1, 100);
        }

        //创建俩个线程
        Thread t1 = new Thread(() -> {//计算偶数
            for (int i = 0; i < longArr.length; i += 2) {
                evenNum += longArr[i];
            }
        });

        Thread t2 = new Thread(() -> {//计算奇数
            for (int i = 1; i < longArr.length; i += 2) {
                oddNum += longArr[i];
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();

        int total = evenNum + oddNum;

        System.out.println(total);
    }

    //实现 Runnable, 重写 run
    public static void main1(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("runnalble run");
            }
        });
    }

    //继承 Thread, 重写 run, 使用匿名内部类
    Thread t0 = new Thread() {
        @Override
        public void run() {
            System.out.println("重写run");
        }
    };
    //实现 Runnable, 重写 run, 使用匿名内部类
    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("override runnanble");
        }
    });
    //lambda表达式
    Thread t2 = new Thread(() -> {
        System.out.println("重写run");
    });
}
